#include <cmath>

#include "globalVariables.h"
#include "DataDefine.h"

void moveRange(int x, int y, int steps);
bool attackRange(int x, int y, int min, int max);
Card* getCard(int id);
int tcpSend(string message);

int gameplayLeftButtonDown()
{
	//handcard 
	if (!isSceneChanging)
	{
		for (Handcard* hcptr : player->handcard)
		{
			if (mouseX >= hcptr->x && mouseX <= hcptr->x + CARD_WIDTH_SMALL
				&& mouseY >= hcptr->y && mouseY <= hcptr->y + CARD_HEIGHT_SMALL)
			{
				if (isPlayerTurn && !isTurnChanging && hcptr->card->canActivate())
				{
					hcptr->isPressed = true;
				}
				//change showing card
				if (cardShown)
				{
					delete cardShown;
				}
				cardShown = getCard(hcptr->card->id);
				isShowingChecker = false;
			}
		}
	}
	//map
	if (!isSceneChanging)
	{
		//in the map
		if (mouseX >= MAP_X && mouseX <= MAP_X + MAP_WIDTH
			&& mouseY >= MAP_Y && mouseY <= MAP_Y + MAP_HEIGHT)
		{
			selectX = (mouseX - MAP_X) / BLOCK_WIDTH;
			selectY = (mouseY - MAP_Y) / BLOCK_HEIGHT;
			if (!isTurnChanging && isPlayerTurn)
			{
				mapSelectBuffer = true;
			}
			//change showing card
			if (board[selectX][selectY])
			{
				if (cardShown)
				{
					delete cardShown;
				}
				cardShown = getCard(board[selectX][selectY]->card->id);
				attackShown = board[selectX][selectY]->card->attack;
				healthShown = board[selectX][selectY]->health;
				moveShown = board[selectX][selectY]->card->move;
				isShowingChecker = true;
			}
		}
	}
	//direct attack
	if (!isSceneChanging)
	{
		if (mouseX >= MAP_X + 2 * BLOCK_WIDTH && mouseX <= MAP_X + 5 * BLOCK_WIDTH
			&& mouseY >= MAP_Y - DIRECT_HEIGHT && mouseY <= MAP_Y)
		{
			isSelectingDirectAttack = true;
		}
	}

	return 0;
}

int gameplayLeftButtonUp()
{
	bool hasSelected = false;
	int distance;
	//map
	if (mapSelectBuffer)
	{
		mapSelectBuffer = false;
		//finish selecting
		if (isSelecting)
		{
			switch (selectState)
			{
			case CARDSELECT:
				if (selectedCard != player->handcard.end() && (*selectedCard)->card->canSelect(selectX, selectY))
				{
					int selectedId = (*selectedCard)->card->id;
					(*selectedCard)->card->activate(selectX, selectY);
					if (!isSinglePlayer)
					{
						tcpSend("ACT " + to_string(selectedId) + " " + to_string(selectX) + " " + to_string(selectY) + " ");
					}
					//shown card clear
					if (cardShown)
					{
						delete cardShown;
						cardShown = NULL;
					}
				}
				break;
			case MOVINGSELECT:
				if (selectedCheckerX != -1 && selectBoard[selectX][selectY])
				{
					//move
					if (selectX != selectedCheckerX || selectY != selectedCheckerY)
					{
						board[selectX][selectY] = board[selectedCheckerX][selectedCheckerY];
						board[selectX][selectY]->xPos = selectX;
						board[selectX][selectY]->yPos = selectY;
						board[selectedCheckerX][selectedCheckerY] = NULL;
						if (!isSinglePlayer)
						{
							tcpSend("MOVE " + to_string(selectX) + " " + to_string(selectY) + " " + to_string(selectedCheckerX) + " " + to_string(selectedCheckerY) + " ");
						}
					}
					//ready to attack
					//clear out
					for (int i = 0; i < 7; i++)
					{
						for (int j = 0; j < 9; j++)
						{
							selectBoard[i][j] = false;
						}
					}
					directAttack = false;
					if (attackRange(selectX, selectY, board[selectX][selectY]->card->minAttackRange, board[selectX][selectY]->card->maxAttackRange))
					{
						hasSelected = true;
						selectState = ENEMYSELECT;
						selectedCheckerX = selectX;
						selectedCheckerY = selectY;
					}
					//cannot attack
					else
					{
						board[selectX][selectY]->hasMoved = true;
					}
				}
				break;
			case ENEMYSELECT:
				//attack
				if (selectedCheckerX != -1 && selectBoard[selectX][selectY])
				{
					//damage
					board[selectX][selectY]->damage(board[selectedCheckerX][selectedCheckerY]->card->attack);
					if (!isSinglePlayer)
					{
						tcpSend("DAMAGE " + to_string(selectX) + " " + to_string(selectY) + " " + to_string(board[selectedCheckerX][selectedCheckerY]->card->attack) + " ");
					}
					//counter attack
					distance = abs(selectX - selectedCheckerX) + abs(selectY - selectedCheckerY);
					if (distance >= board[selectX][selectY]->card->minAttackRange && distance <= board[selectX][selectY]->card->maxAttackRange)
					{
						board[selectedCheckerX][selectedCheckerY]->damage(board[selectX][selectY]->card->attack);
						if (!isSinglePlayer)
						{
							tcpSend("DAMAGE " + to_string(selectedCheckerX) + " " + to_string(selectedCheckerY) + " " + to_string(board[selectX][selectY]->card->attack) + " ");
						}
					}
					//moved
					board[selectedCheckerX][selectedCheckerY]->hasMoved = true;
					//shown card clear
					if (cardShown)
					{
						delete cardShown;
						cardShown = NULL;
					}
				}
				//finish
				else
				{
					board[selectedCheckerX][selectedCheckerY]->hasMoved = true;
				}
				break;
			}
		}
		//select checker
		else
		{
			if (board[selectX][selectY] && !board[selectX][selectY]->isEnemy && !board[selectX][selectY]->hasMoved)
			{
				hasSelected = true;
				isSelecting = true;
				selectState = MOVINGSELECT;
				//position save
				selectedCheckerX = selectX;
				selectedCheckerY = selectY;
				//select board clear
				for (int i = 0; i < 7; i++)
				{
					for (int j = 0; j < 9; j++)
					{
						selectBoard[i][j] = false;
					}
				}
				//select board setting
				selectBoard[selectX][selectY] = true;
				moveRange(selectX, selectY, board[selectX][selectY]->card->move);
			}
		}
	}
	//direct attack
	if (isSelectingDirectAttack)
	{
		isSelectingDirectAttack = false;
		enemyPlayer->damage(board[selectedCheckerX][selectedCheckerY]->card->attack);
		if (!isSinglePlayer)
		{
			tcpSend("DIRECT " + to_string(board[selectedCheckerX][selectedCheckerY]->card->attack) + " ");
		}
	}

	//handcard
	for (Handcard* hcptr : player->handcard)
	{
		if (hcptr->isPressed)
		{
			hcptr->isPressed = false;
			hcptr->press();
		}
		//handcard release
		else
		{
			hcptr->release();
		}
	}
	//handcard select state confirm
	auto hciter = player->handcard.begin();
	for (Handcard* hcptr : player->handcard)
	{
		if (hcptr->isSelected)
		{
			hasSelected = true;
			isSelecting = true;
			selectState = CARDSELECT;
			selectedCard = hciter;
			break;
		}
		hciter++;
	}
	//out of select
	if (!hasSelected)
	{
		if (isSelecting && selectState == ENEMYSELECT)
		{
			board[selectedCheckerX][selectedCheckerY]->hasMoved = true;
		}
		isSelecting = false;
		selectedCheckerX = -1;
		selectedCheckerY = -1;
	}

	return 0;
}

void moveRange(int x, int y, int steps)
{
	if (steps <= 0)
	{
		return;
	}
	if (x > 0)
	{
		if (!board[x - 1][y])
		{
			selectBoard[x - 1][y] = true;
			moveRange(x - 1, y, steps - 1);
		}
		else if (!board[x - 1][y]->isEnemy)
		{
			moveRange(x - 1, y, steps - 1);
		}
	}
	if (x < 6)
	{
		if (!board[x + 1][y])
		{
			selectBoard[x + 1][y] = true;
			moveRange(x + 1, y, steps - 1);
		}
		else if (!board[x + 1][y]->isEnemy)
		{
			moveRange(x + 1, y, steps - 1);
		}
	}
	if (y > 0)
	{
		if (!board[x][y - 1])
		{
			selectBoard[x][y - 1] = true;
			moveRange(x, y - 1, steps - 1);
		}
		else if (!board[x][y - 1]->isEnemy)
		{
			moveRange(x, y - 1, steps - 1);
		}
	}
	if (y < 8)
	{
		if (!board[x][y + 1])
		{
			selectBoard[x][y + 1] = true;
			moveRange(x, y + 1, steps - 1);
		}
		else if (!board[x][y + 1]->isEnemy)
		{
			moveRange(x, y + 1, steps - 1);
		}
	}
}

bool attackRange(int x, int y, int min, int max)
{
	bool hasTarget = false;
	if (max <= 0)
	{
		return false;
	}
	if (x > 0)
	{
		if (board[x - 1][y] && board[x - 1][y]->isEnemy && min <= 1)
		{
			selectBoard[x - 1][y] = true;
			hasTarget = true;
			hasTarget |= attackRange(x - 1, y, min - 1, max - 1);
		}
		else
		{
			hasTarget |= attackRange(x - 1, y, min - 1, max - 1);
		}
	}
	if (x < 6)
	{
		if (board[x + 1][y] && board[x + 1][y]->isEnemy && min <= 1)
		{
			selectBoard[x + 1][y] = true;
			hasTarget = true;
			hasTarget |= attackRange(x + 1, y, min - 1, max - 1);
		}
		else
		{
			hasTarget |= attackRange(x + 1, y, min - 1, max - 1);
		}
	}
	if (y > 0)
	{
		if (board[x][y - 1] && board[x][y - 1]->isEnemy && min <= 1)
		{
			selectBoard[x][y - 1] = true;
			hasTarget = true;
			hasTarget |= attackRange(x, y - 1, min - 1, max - 1);
		}
		else
		{
			hasTarget |= attackRange(x, y - 1, min - 1, max - 1);
		}
	}
	//direct attack judge
	else
	{
		if (max >= 1 && x >= 2 && x <= 4)
		{
			directAttack = true;
			hasTarget = true;
		}
	}
	if (y < 8)
	{
		if (board[x][y + 1] && board[x][y + 1]->isEnemy && min <= 1)
		{
			selectBoard[x][y + 1] = true;
			hasTarget = true;
			hasTarget |= attackRange(x, y + 1, min - 1, max - 1);
		}
		else
		{
			hasTarget |= attackRange(x, y + 1, min - 1, max - 1);
		}
	}
	return hasTarget;
}